package com.fowo.api.syncAmazon.monitor;

import com.fowo.api.syncAmazon.entity.CurrencyDetail;
import com.fowo.api.syncAmazon.mapper.DataConnectivityMonitorMapper;
import com.fowo.api.sys.service.impl.SysMailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.mail.MessagingException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import static java.lang.Thread.sleep;

/**
 * @description: 监控数据从mysql到starrocks的连通性
 * @author: xqw
 * @time: 2024/4/28 13:25
 */
@Component
public class DataConnectivityMonitor {

    @Autowired
    protected DataConnectivityMonitorMapper dataConnectivityMonitorMapper;

    @Autowired
    protected SysMailServiceImpl sysMailService;

    @Value("${spring.mail.addressee}")
    private String addressee;

    private static final String EMAIL_SUBJECT_PREFIX = "'MySQL到StarRocks连通性报警--";

    /**
     * 测试连通性时 等待的时间（s）
     */
    private final Integer sleepTime = 60;

    /**
     * 监控任务入口
     * 往mysql中插入一条数据，等待一定时间后，查询这条数据在starrocks中是否存在，如果不存在则（循环3次），再等待一定时间，如果仍旧不存在则发出邮件报警
     */
    public void entrance() {
        // 构造出一条记录作为测试数据
        CurrencyDetail testDate = createTestDate();

        // 验证mysql到StarRocks 是否连通
        boolean success = verify(testDate);

        // 连通性测试未通过，则发出邮件报警
        if (!success) {
            // 构造告警模板数据
            Map<String, Object> variables = createTemplateData("数据从MySQL到StarRocks的连通性监控", "MySQL到StarRocks连通性测试失败");

            //发出邮件报警
            try {
                sysMailService.send(addressee, EMAIL_SUBJECT_PREFIX + LocalDate.now() + "'","monitor-alarm.html", variables);
            } catch (MessagingException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private Map<String, Object> createTemplateData(String monitorName, String message) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("monitorName", monitorName);
        variables.put("appearTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSS")));
        variables.put("message", message);
        return variables;
    }

    /**
     * 验证mysql到StarRocks 是否连通性
     * @param testDate 测试数据
     * @return 是否连通
     */
    private boolean verify(CurrencyDetail testDate) {
        int times = 0;
        int retryCount = 3;

        // 将测试数据 插入 mysql 数据库
        if (dataConnectivityMonitorMapper.selectById(testDate.getId()) == null) {
            dataConnectivityMonitorMapper.insert(testDate);
        } else {
            dataConnectivityMonitorMapper.update(testDate);
        }

        // 等待并验证连通性 循环三次
        while (times < retryCount) {
            // 等待 60s
            try {
                sleep(sleepTime * 1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            times++;

            // 在starrocks中查询这条数据是否存在
            CurrencyDetail result = dataConnectivityMonitorMapper.selectStarRocksById(testDate);
            // 如果存在,则测试通过，结束方法
            if (result != null && testDate.getRatio().toString().equals(result.getRatio().toString())) {
                return true;
            }
        }
        return false;
    }

    private CurrencyDetail createTestDate() {
        CurrencyDetail testData = new CurrencyDetail();
        testData.setId(0);
        testData.setFromCurrency("测试");
        testData.setToCurrency("测试");
        // 为该字段构造一个随机值，以便更好的测试连通性
        testData.setRatio(Double.valueOf(String.format("%.6f", new Random(System.currentTimeMillis()).nextDouble())));
        return testData;
    }


}
